package ru.evreke

import ClientMessage
import GenericMessage
import JoinMessage
import Message
import PlaceShipMessage
import ShotMessage
import io.ktor.serialization.kotlinx.*
import io.ktor.server.application.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
import io.ktor.websocket.*
import kotlinx.serialization.json.Json
import org.koin.ktor.ext.inject
import ru.evreke.service.MessageHandlerService
import ru.evreke.service.socket.WebsocketSessionService
import java.util.*

fun Application.sockets() {
    install(WebSockets) {
        contentConverter = KotlinxWebsocketSerializationConverter(Json)
    }

    val messageHandlerService by inject<MessageHandlerService>()
    val websocketSessionService by inject<WebsocketSessionService>()
    val log by lazy { log }

    routing {
        webSocket("/ws") {
            val playerUUID = UUID.randomUUID().toString()
            websocketSessionService.addPlayerAndWsSession(playerUUID, this)
            log.debug("Player $playerUUID started session")

            try {
                while (true) {
                    val message = receiveDeserialized<ClientMessage>()
                    log.debug("Player {} send message - {}", playerUUID, message)
                    when (message) {
                        is GenericMessage -> {
                            val response = when (message.message) {
                                Message.INIT -> {
                                    messageHandlerService.handleInitMessage(playerUUID)
                                }

                                Message.JOIN -> {
                                    messageHandlerService.handleJoinMessage()
                                }
                            }
                            sendSerialized(response)
                        }

                        is ShotMessage -> {
                            messageHandlerService.handleShotMessage(message)
                        }

                        is JoinMessage -> {
                            messageHandlerService.handleJoinMessage(message, playerUUID)
                        }

                        is PlaceShipMessage -> {
                            messageHandlerService.handlePlaceShip(message, playerUUID)
                        }
                    }
                    log.debug("Message handled")
                }
            } catch (e: RuntimeException) {
                println("Error $e")
            } finally {
                websocketSessionService.removePlayerWsSession(playerUUID)
                this.close()
            }
        }
    }
}
